from twisted.internet import reactor, defer
from json import dumps
from mediadart.mqueue.mqserver import startMQ, MQServer
from mediadart.utils import default_start_mqueue, get_mq_params
from mediadart import log
from mediadart.rest.proxy import doHTTP



class FooError(Exception):
    pass

#
# The Dummy MQServer handling requests for Foo
#
class FooServer(MQServer):
    def __init__(self):
        MQServer.__init__(self)
        self.impl = Foo()

    def updater(self, update_url, percentage, d, msg):
        def log_all(*args):
            log.debug('%s' % str(args))

        if percentage >= 100:
            d.callback(dumps(msg))
        else:
            percentage += 10
            f = doHTTP(update_url, dumps({'completion':percentage}))
            f.deferred.addBoth(log_all)
            reactor.callLater(1, self.long_run, update_url, percentage, d, msg)
            return d
        
    def mq_product(self, a, b):
        "a short, blocking method, no updates"
        log.debug('\n\n********* FooServer.block_method(%s, %s)\n' % (a, b))
        return  self.impl.product(a, b)

    def mq_fail_product(self, a, b):
        "a short, blocking method that fails"
        log.debug('\n\n********* FooServer.short_method(%s)\n' % a)
        raise FooError('ecco un errore')

    def mq_updating_product(self, a, b, update_url):
        "a long methodwith with progress updates"
        d=defer.Deferred()
        self.impl.updating_product(update_url, a, b, d)
        return d

#
# A separate Foo implementation makes it possible to call Foo methods directly
#
class Foo:
    def wait_one_sec(self):
        "utility function for spending some time in a twisted friendly way"
        d = defer.Deferred()
        reactor.callLater(1, d.callback, 'ok')
        return d

    def update(self, update_url, percentage):
        # sends update messages
        if update_url:
            doPost(update_url, dumps({'completion':percentage}))

    def product(self, a, b):
        return "%s x %s = %s" % (a, b, a*b)

    @defer.inlineCallbacks
    def updating_product(self, update_url, a, b, deferred):
        """This is an example to a method that returns the response, as usual, but
         also sends update messages.
         
        This method accepts an url arguments to which sends json encoded POSTS
        with progress reports.
        """
        for n in xrange(10):
            self.update(update_url, 10*n)
            print('still working')
            yield self.wait_one_sec()
        deferred.callback("%s x %s = %s" % (a, b, a*b))

def start():
    default_start_mqueue(FooServer, [])

if __name__=='__main__':
    #startMQ(Calculator, 'localhost', 5672, 'guest', 'guest')
    reactor.run()

